home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / aztecnos.arc / SOCKET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-20  |  35.3 KB  |  1,570 lines

  1. #include <stdio.h>
  2. #ifdef    __STDC__
  3. #include <stdarg.h>
  4. #endif
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "netuser.h"
  8. #include "timer.h"
  9. #include "iface.h"
  10. #include "ip.h"
  11. #include "tcp.h"
  12. #include "udp.h"
  13. #include "ax25.h"
  14. #include "lapb.h"
  15. #include "proc.h"
  16. #include "usock.h"
  17. #include "socket.h"
  18. #include "config.h"
  19.  
  20. extern int errno;
  21. extern char *Tcpstates[],*Tcpreasons[],*Axreasons[];
  22. extern char *Ax25states[];
  23. extern char *pinet();
  24. extern int32 Ip_addr;
  25. extern int16 Lport;
  26. void s_arcall(),s_atcall(),s_ascall();
  27. static void s_trcall(),s_ttcall(),s_tscall(),s_urcall(),trdiscard();
  28. static int checkaddr();
  29. static void autobind();
  30. extern struct usock *itop();
  31.  
  32. char *Socktypes[] = {
  33.     "Not Used",
  34.     "TCP",
  35.     "UDP",
  36.     "AX25 I",
  37.     "AX25 UI",
  38.     "Raw IP"
  39. };
  40. struct usock *Usock;    /* Socket entry array */
  41. int Nusock;        /* Number of socket entries */
  42.  
  43. /* The following two variables are needed because there can be only one
  44.  * socket listening on each of the AX.25 modes (I and UI)
  45.  */
  46. #ifdef    AX25
  47. int axi_sock = -1;    /* Socket number listening for AX25 connections */
  48. int axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  49. struct mbuf *bcq;    /* Queue of incoming UI frames */
  50.  
  51. /* Function that handles incoming UI frames from lapb.c */
  52. void
  53. beac_input(iface,src,bp)
  54. struct iface *iface;
  55. struct ax25_addr *src;
  56. struct mbuf *bp;
  57. {
  58.     struct mbuf *hdr;
  59.     struct sockaddr_ax *sax;
  60.  
  61.     if(axui_sock == -1){
  62.         /* Nobody there to read it */
  63.         free_p(bp);
  64.     } else {
  65.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  66.             free_p(bp);
  67.             return;
  68.         }
  69.         sax = (struct sockaddr_ax *)hdr->data;
  70.         sax->sax_family = AF_AX25;
  71.         memcpy((char *)&sax->ax25_addr,(char *)src,sizeof(struct ax25_addr));
  72.         strncpy((char *)&sax->iface,iface->name,ILEN);
  73.         hdr->next = bp;
  74.         enqueue(&bcq,hdr);
  75.     }
  76. }
  77. #endif
  78.  
  79. /* Initialize user socket array with specified number of entries */
  80. sockinit(n)
  81. int n;        /* Number of socket entries */
  82. {
  83.     if(Nusock != 0)
  84.         return;    /* Already initialized */
  85.     Nusock = n;
  86.     Usock = (struct usock *)calloc(n,sizeof(struct usock));
  87. }
  88.  
  89. /* Create a user socket, return socket index
  90.  * The mapping to actual protocols is as follows:
  91.  *        
  92.  *        
  93.  * ADDRESS FAMILY    Stream        Datagram    Raw
  94.  *
  95.  * AF_INET        TCP        UDP        IP
  96.  * AF_AX25        I-frames    UI-frames
  97.  */
  98. int
  99. socket(af,type,protocol)
  100. int af;        /* Address family */
  101. int type;    /* Stream or datagram */
  102. int protocol;    /* Used for raw IP sockets */
  103. {
  104.     register struct usock *up;
  105.  
  106.     for(up=Usock;up < &Usock[Nusock];up++)
  107.         if(up->type == NOTUSED)
  108.             break;
  109.  
  110.     if(up == &Usock[Nusock]){
  111.         /* None left */
  112.         errno = EMFILE;
  113.         return -1;
  114.     }
  115.     errno = 0;
  116.     up->noblock = 0;
  117.     up->rdysock = -1;
  118.     up->cb.p = NULLCHAR;
  119.     up->peername = up->name = NULLCHAR;
  120.     up->namelen = up->peernamelen = 0;
  121.     up->owner = Curproc;
  122.     memset(up->errcodes,0,sizeof(up->errcodes));
  123.     switch(af){
  124. #ifdef    AX25
  125.     case AF_AX25:
  126.         switch(type){
  127.         case SOCK_STREAM:
  128.             up->type = TYPE_AX25I;
  129.             break;
  130.         case SOCK_DGRAM:
  131.             up->type = TYPE_AX25UI;
  132.             break;
  133.         default:
  134.             errno = ESOCKTNOSUPPORT;
  135.             break;
  136.         }
  137.         break;
  138. #endif
  139.     case AF_INET:
  140.         switch(type){
  141.         case SOCK_STREAM:
  142.             up->type = TYPE_TCP;
  143.             break;
  144.         case SOCK_DGRAM:
  145.             up->type = TYPE_UDP;
  146.             break;
  147.         case SOCK_RAW:
  148.             up->type = TYPE_RAW;
  149.             up->cb.rip = raw_ip(protocol);
  150.             break;
  151.         default:
  152.             errno = ESOCKTNOSUPPORT;
  153.             break;
  154.         }
  155.         break;
  156.     default:
  157.         errno = EAFNOSUPPORT;
  158.         break;
  159.     }
  160.     if(errno)
  161.         return -1;
  162.  
  163.     return up - Usock;
  164. }
  165.  
  166. /* Attach a local address/port to a socket. If not issued before a connect
  167.  * or listen, will be issued automatically
  168.  */
  169. int
  170. bind(s,name,namelen)
  171. int s;        /* Socket index */
  172. char *name;    /* Local name */
  173. int namelen;    /* Length of name */
  174. {
  175.     register struct usock *up;
  176.     union sp local;
  177.     struct socket lsock;
  178.  
  179.     if((up = itop(s)) == NULLUSOCK){
  180.         errno = EBADF;
  181.         return -1;
  182.     }
  183.     if(name == NULLCHAR){
  184.         errno = EFAULT;
  185.         return -1;
  186.     }
  187.     if(up->name != NULLCHAR){
  188.         /* Bind has already been issued */
  189.         errno = EINVAL;
  190.         return -1;
  191.     }
  192.     if(checkaddr(up->type,name,namelen) == -1){
  193.         /* Incorrect length or family for chosen protocol */
  194.         errno = EAFNOSUPP;
  195.         return -1;    
  196.     }
  197.     /* Stash name in an allocated block */
  198.     up->namelen = namelen;
  199.     up->name = malloc(namelen);
  200.     memcpy(up->name,name,namelen);
  201.     /* Create control block for datagram sockets */
  202.     switch(up->type){
  203.     case TYPE_UDP:
  204.         local.in = (struct sockaddr_in *)up->name;
  205.         lsock.address = local.in->sin_addr.s_addr;
  206.         lsock.port = local.in->sin_port;
  207.         up->cb.udp = open_udp(&lsock,s_urcall);
  208.         break;
  209. #ifdef    AX25
  210.     case TYPE_AX25UI:
  211.         if(axui_sock != -1){
  212.             errno = EADDRINUSE;
  213.             return -1;
  214.         }
  215.         axui_sock = s;
  216.         break;
  217. #endif
  218.     }
  219.     return 0;
  220. }
  221. /* Post a listen on a socket */
  222. int
  223. listen(s,backlog)
  224. int s;        /* Socket index */
  225. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  226. {
  227.     register struct usock *up;
  228.     union sp local;
  229.     struct socket lsock;
  230.  
  231.     if((up = itop(s)) == NULLUSOCK){
  232.         errno = EBADF;
  233.         return -1;
  234.     }
  235.     if(up->cb.p != NULLCHAR){
  236.         errno = EISCONN;
  237.         return -1;
  238.     }
  239.     switch(up->type){
  240.     case TYPE_TCP:
  241.         if(up->name == NULLCHAR)
  242.             autobind(s,AF_INET);
  243.  
  244.         local.in = (struct sockaddr_in *)up->name;
  245.         lsock.address = local.in->sin_addr.s_addr;
  246.         lsock.port = local.in->sin_port;
  247.         up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  248.          backlog ? TCP_SERVER:TCP_PASSIVE,0,
  249.         s_trcall,s_ttcall,s_tscall,0,s);
  250.         break;
  251.     case TYPE_AX25I:
  252.         if(up->name == NULLCHAR)
  253.             autobind(s,AF_AX25);
  254.         
  255.         break;    /* TO BE IMPLEMENTED */
  256.     default:
  257.         /* Listen not supported on datagram sockets */
  258.         errno = EOPNOTSUPP;
  259.         return -1;        
  260.     }
  261.     return 0;
  262. }
  263. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  264. int
  265. connect(s,peername,peernamelen)
  266. int s;            /* Socket index */
  267. char *peername;        /* Peer name */
  268. int peernamelen;    /* Length of peer name */
  269. {
  270.     register struct usock *up;
  271.     union cb cb;
  272.     union sp local,remote;
  273.     struct socket lsock,fsock;
  274.     struct iface *iface;
  275.  
  276.     if((up = itop(s)) == NULLUSOCK){
  277.         errno = EBADF;
  278.         return -1;
  279.     }
  280.     if(peername == NULLCHAR){
  281.         /* Connect must specify a remote address */
  282.         errno = EFAULT;
  283.         return -1;
  284.     }
  285.     if(checkaddr(up->type,peername,peernamelen) == -1){
  286.         errno = EAFNOSUPPORT;
  287.         return -1;
  288.     }
  289.     /* Raw socket control blocks are created in socket() */
  290.     if(up->type != TYPE_RAW && up->cb.p != NULLCHAR){
  291.         errno = EISCONN;
  292.         return -1;
  293.     }
  294.     if((up->peername = malloc(peernamelen)) == NULLCHAR){
  295.         errno = ENOMEM;
  296.         return -1;
  297.     }
  298.     memcpy(up->peername,peername,peernamelen);
  299.     up->peernamelen = peernamelen;
  300.  
  301.     /* Set up the local socket structures for TCP and UDP */
  302.     if(up->name == NULLCHAR){
  303.         switch(up->type){
  304.         case TYPE_TCP:
  305.         case TYPE_UDP:
  306.         case TYPE_RAW:
  307.             autobind(s,AF_INET);
  308.             break;
  309.         case TYPE_AX25I:
  310.         case TYPE_AX25UI:
  311.             autobind(s,AF_AX25);
  312.             break;
  313.         }
  314.     }
  315.     switch(up->type){
  316.     case TYPE_TCP:
  317.         /* Construct the TCP-style ports from the sockaddr structs */
  318.         local.in = (struct sockaddr_in *)up->name;
  319.         lsock.address = local.in->sin_addr.s_addr;
  320.         lsock.port = local.in->sin_port;
  321.  
  322.         remote.in = (struct sockaddr_in *)up->peername;
  323.         fsock.address = remote.in->sin_addr.s_addr;
  324.         fsock.port = remote.in->sin_port;
  325.  
  326.         /* Open the TCB in active mode */
  327.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  328.          s_trcall,s_ttcall,s_tscall,0,s);
  329.  
  330.         /* Wait for the connection to complete */
  331.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != ESTABLISHED){
  332.             if(up->noblock){
  333.                 errno = EWOULDBLOCK;
  334.                 return -1;
  335.             } else if(pwait(&cb.tcb->state) != 0){
  336.                 errno = EINTR;
  337.                 return -1;
  338.             }
  339.         }
  340.         if(cb.tcb == NULLTCB){
  341.             /* Probably got refused */
  342.             if(up->peername != NULLCHAR)
  343.                 free(up->peername);
  344.             up->peername = NULLCHAR;
  345.             errno = ECONNREFUSED;
  346.             return -1;
  347.         }
  348.         break;
  349.     case TYPE_UDP:
  350.     case TYPE_AX25UI:
  351.     case TYPE_RAW:
  352.         /* Control block already created by bind() */
  353.         break;
  354. #ifdef    AX25
  355.     case TYPE_AX25I:
  356.         local.ax = (struct sockaddr_ax *)up->name;
  357.         remote.ax = (struct sockaddr_ax *)up->peername;
  358.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  359.             errno = EINVAL;
  360.             return -1;
  361.         }
  362.         up->cb.ax25 = open_ax25(iface,
  363.          (struct ax25_addr *)&local.ax->ax25_addr,
  364.          (struct ax25_addr *)&remote.ax->ax25_addr,
  365.          2048,s_arcall,s_atcall,s_ascall,s);
  366.  
  367.         /* Wait for the connection to complete */
  368.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != CONNECTED){
  369.             if(up->noblock){
  370.                 errno = EWOULDBLOCK;
  371.                 return -1;
  372.             } else if(pwait(&cb.ax25->state) != 0){
  373.                 errno = EINTR;
  374.                 return -1;
  375.             }
  376.         }
  377.         if(cb.ax25 == NULLAX25){
  378.             /* Connection probably already exists */
  379.             if(up->peername != NULLCHAR)
  380.                 free(up->peername);
  381.             up->peername = NULLCHAR;
  382.             errno = ECONNREFUSED;
  383.             return -1;
  384.         }
  385.         break;
  386. #endif
  387.     }
  388.     return 0;
  389. }
  390. /* Wait for a connection. Valid only for connection-oriented sockets. */
  391. int
  392. accept(s,peername,peernamelen)
  393. int s;            /* Socket index */
  394. char *peername;        /* Peer name */
  395. int *peernamelen;    /* Length of peer name */
  396. {
  397.     int i;
  398.     register struct usock *up;
  399.  
  400.     if((up = itop(s)) == NULLUSOCK){
  401.         errno = EBADF;
  402.         return -1;
  403.     }
  404.     if(up->cb.p == NULLCHAR){
  405.         errno = EOPNOTSUPP;
  406.         return -1;
  407.     }
  408.     /* Accept is valid only for stream sockets */
  409.     switch(up->type){
  410.     case TYPE_TCP:
  411.     case TYPE_AX25I:
  412.         break;
  413.     default:
  414.         errno = EOPNOTSUPP;
  415.         return -1;
  416.     }    
  417.     /* Wait for the state-change upcall routine to signal us */
  418.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  419.         if(up->noblock){
  420.             errno = EWOULDBLOCK;
  421.             return -1;
  422.         } else if(pwait(up) != 0){
  423.             errno = EINTR;
  424.             return -1;
  425.         }
  426.     }
  427.     if(up->cb.p == NULLCHAR){
  428.         /* Blown away */
  429.         errno = EBADF;
  430.         return -1;
  431.     }
  432.     i = up->rdysock;
  433.     up->rdysock = -1;
  434.  
  435.     up = &Usock[i];
  436.     if(peername != NULLCHAR && peernamelen != NULL){
  437.         *peernamelen = min(up->peernamelen,*peernamelen);
  438.         memcpy(peername,up->peername,*peernamelen);
  439.     }
  440.     return i;
  441. }
  442. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  443.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  444.  * the len parameter.
  445.  */
  446. int
  447. recv_mbuf(s,bpp,len,flags,from,fromlen)
  448. int s;            /* Socket index */
  449. struct mbuf **bpp;    /* Place to stash receive buffer */
  450. int len;        /* Maximum length to read (0 implies all) */
  451. int flags;        /* Unused; will control out-of-band data, etc */
  452. char *from;        /* Peer address (only for datagrams) */
  453. int *fromlen;        /* Length of peer address */
  454. {
  455.     register struct usock *up;
  456.     int cnt;
  457.     union cb cb;
  458.     struct socket fsocket;
  459.     union sp remote;
  460.     struct ip ip;
  461.     struct mbuf *bp;
  462.  
  463.     if((up = itop(s)) == NULLUSOCK){
  464.         errno = EBADF;
  465.         return -1;
  466.     }
  467.     if(up->cb.p == NULLCHAR){
  468.         errno = ENOTCONN;
  469.         return -1;
  470.     }
  471.     switch(up->type){
  472.     case TYPE_TCP:
  473.         if(up->cb.tcb->r_upcall == trdiscard){
  474.             /* Receive shutdown has been done */
  475.             errno = ENOTCONN;    /* CHANGE */
  476.             return -1;
  477.         }
  478.         while((cb.tcb = up->cb.tcb) != NULLTCB
  479.                  && (cnt = recv_tcp(cb.tcb,&bp,len)) == -1){
  480.             if(up->noblock){
  481.                 errno = EWOULDBLOCK;
  482.                 return -1;
  483.             } else if(pwait(&cb.tcb->rcvq) != 0){
  484.                 errno = EINTR;
  485.                 return -1;
  486.             }
  487.         }
  488.         if(cb.tcb == NULLTCB){
  489.             /* Connection went away */
  490.             errno = ENOTCONN;
  491.             return -1;
  492.         }
  493.         break;
  494.     case TYPE_UDP:
  495.         while((cb.udp = up->cb.udp) != NULLUDP
  496.         && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  497.             if(up->noblock){
  498.                 errno = EWOULDBLOCK;
  499.                 return -1;
  500.             } else if(pwait(&cb.udp->rcvq) != 0){
  501.                 errno = EINTR;
  502.                 return -1;
  503.             }
  504.         }
  505.         if(cb.udp == NULLUDP){
  506.             /* Connection went away */
  507.             errno = ENOTCONN;
  508.             return -1;
  509.         }
  510.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  511.             remote.in = (struct sockaddr_in *)from;
  512.             remote.in->sin_family = AF_INET;
  513.             remote.in->sin_addr.s_addr = fsocket.address;
  514.             remote.in->sin_port = fsocket.port;
  515.             *fromlen = SOCKSIZE;
  516.         }
  517.         break;
  518.     case TYPE_RAW:
  519.         while((cb.rip = up->cb.rip) != NULLRIP && cb.rip->rcvq == NULLBUF){
  520.             if(up->noblock){
  521.                 errno = EWOULDBLOCK;
  522.                 return -1;
  523.             } else if(pwait(&cb.rip->rcvq) != 0){
  524.                 errno = EINTR;
  525.                 return -1;
  526.             }
  527.         }
  528.         if(cb.rip == NULLRIP){
  529.             /* Connection went away */
  530.             errno = ENOTCONN;
  531.             return -1;
  532.         }
  533.         bp = dequeue(&cb.rip->rcvq);
  534.         ntohip(&ip,&bp);
  535.         cnt = len_mbuf(bp);
  536.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  537.             remote.in = (struct sockaddr_in *)from;
  538.             remote.in->sin_family = AF_INET;
  539.             remote.in->sin_addr.s_addr = ip.source;
  540.             remote.in->sin_port = 0;
  541.             *fromlen = SOCKSIZE;
  542.         }
  543.         break;
  544. #ifdef    AX25
  545.     case TYPE_AX25I:
  546.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  547.          && (bp = recv_ax25(cb.ax25,len)) == NULLBUF){
  548.             if(up->noblock){
  549.                 errno = EWOULDBLOCK;
  550.                 return -1;
  551.             } else if(pwait(&cb.ax25->rxq) != 0){
  552.                 errno = EINTR;
  553.                 return -1;
  554.             }
  555.         }
  556.         if(cb.ax25 == NULLAX25){
  557.             /* Connection went away */
  558.             errno = ENOTCONN;
  559.             return -1;
  560.         }
  561.         break;
  562.     case TYPE_AX25UI:
  563.         while(s == axui_sock && bcq == NULLBUF){
  564.             if(up->noblock){
  565.                 errno = EWOULDBLOCK;
  566.                 return -1;
  567.             } else if(pwait(&bcq) != 0){
  568.                 errno = EINTR;
  569.                 return -1;
  570.             }
  571.         }
  572.         if(s != axui_sock){
  573.             errno = ENOTCONN;
  574.             return -1;
  575.         }
  576.         bp = dequeue(&bcq);
  577.  
  578.         if(from != NULLCHAR && fromlen != NULLINT && *fromlen >= SOCKSIZE){
  579.             pullup(&bp,(char *)from,SOCKSIZE);
  580.             *fromlen = SOCKSIZE;
  581.         } else {
  582.             pullup(&bp,NULLCHAR,SOCKSIZE);
  583.         }
  584.         break;
  585. #endif
  586.     }
  587.     if(bpp != NULLBUFP)
  588.         *bpp = bp;
  589.     return cnt;
  590. }
  591. /* Low level send routine; user supplies mbuf for transmission. More
  592.  * efficient than send() or sendto(), the higher level interfaces.
  593.  * The "to" and "tolen" parameters are ignored on connection-oriented
  594.  * sockets.
  595.  *
  596.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  597.  */
  598. int
  599. send_mbuf(s,bp,flags,to,tolen)
  600. int s;            /* Socket index */
  601. struct mbuf *bp;    /* Buffer to send */
  602. int flags;        /* not currently used */
  603. char *to;        /* Destination, only for datagrams */
  604. int tolen;        /* Length of destination */
  605. {
  606.     register struct usock *up;
  607.     union cb cb;
  608.     union sp local,remote;
  609.     struct socket lsock,fsock;
  610.     int cnt;
  611.  
  612.     if((up = itop(s)) == NULLUSOCK){
  613.         free_p(bp);
  614.         errno = EBADF;
  615.         return -1;
  616.     }
  617.     if(up->name == NULLCHAR){
  618.         /* Automatic local name assignment for datagram sockets */
  619.         switch(up->type){
  620.         case TYPE_UDP:
  621.         case TYPE_RAW:
  622.             autobind(s,AF_INET);
  623.             break;
  624.         case TYPE_AX25UI:
  625.             autobind(s,AF_AX25);
  626.             break;
  627.         default:
  628.             free_p(bp);
  629.             errno = ENOTCONN;
  630.             return -1;
  631.         }
  632.     }
  633.     cnt = len_mbuf(bp);
  634.     switch(up->type){
  635.     case TYPE_TCP:
  636.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  637.             free_p(bp);
  638.             errno = ENOTCONN;
  639.             return -1;
  640.         }        
  641.         cnt = send_tcp(cb.tcb,bp);
  642.  
  643.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  644.          cb.tcb->sndcnt > cb.tcb->window){
  645.             /* Send queue is full */
  646.             if(up->noblock){
  647.                 errno = EWOULDBLOCK;
  648.                 return -1;
  649.             } else if(pwait(&cb.tcb->sndq) != 0){
  650.                 errno = EINTR;
  651.                 return -1;
  652.             }
  653.         }
  654.          if(cb.tcb == NULLTCB){
  655.             errno = ENOTCONN;
  656.             return -1;
  657.         }
  658.         break;
  659.     case TYPE_UDP:
  660.         local.in = (struct sockaddr_in *)up->name;
  661.         lsock.address = local.in->sin_addr.s_addr;
  662.         lsock.port = local.in->sin_port;
  663.         if(to != NULLCHAR)
  664.             remote.in = (struct sockaddr_in *)to;
  665.         else if(up->peername != NULLCHAR)
  666.             remote.in = (struct sockaddr_in *)up->peername;
  667.         else {
  668.             errno = ENOTCONN;
  669.             return -1;
  670.         }    
  671.         fsock.address = remote.in->sin_addr.s_addr;
  672.         fsock.port = remote.in->sin_port;
  673.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  674.         break;
  675.     case TYPE_RAW:
  676.         local.in = (struct sockaddr_in *)up->name;
  677.         if(to != NULLCHAR)
  678.             remote.in = (struct sockaddr_in *)to;
  679.         else if(up->peername != NULLCHAR)
  680.             remote.in = (struct sockaddr_in *)up->peername;
  681.         else {
  682.             errno = ENOTCONN;
  683.             return -1;
  684.         }    
  685.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  686.             up->cb.rip->protocol,0,0,bp,0,0,0);
  687.         break;
  688. #ifdef    AX25
  689.     case TYPE_AX25I:
  690.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  691.             free_p(bp);
  692.             errno = ENOTCONN;
  693.             return -1;
  694.         }
  695.         send_ax25(cb.ax25,bp,PID_NO_L3);
  696.  
  697.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  698.          len_q(cb.ax25->txq) > cb.ax25->window){
  699.             if(up->noblock){
  700.                 errno = EWOULDBLOCK;
  701.                 return -1;
  702.             } else if(pwait(&cb.ax25->txq) != 0){
  703.                 errno = EINTR;
  704.                 return -1;
  705.             }
  706.         }
  707.         if(cb.ax25 == NULLAX25){
  708.             errno = EBADF;
  709.             return -1;
  710.         }
  711.         break;
  712.     case TYPE_AX25UI:
  713.         local.ax = (struct sockaddr_ax *)up->name;
  714.         if(to != NULLCHAR)
  715.             remote.ax = (struct sockaddr_ax *)to;
  716.         else if(up->peername != NULLCHAR)
  717.             remote.ax = (struct sockaddr_ax *)up->peername;
  718.         else {
  719.             errno = ENOTCONN;
  720.             return -1;
  721.         }
  722.         ax_output(NULLIF,(char *)&remote.ax->ax25_addr,
  723.          (char *)&local.ax->ax25_addr,PID_NO_L3,bp);
  724.         break;
  725. #endif
  726.     }    
  727.     return cnt;
  728. }
  729. /* Higher-level receive routine, intended for connection-oriented sockets.
  730.  * Can be used with datagram sockets, although the sender id is lost.
  731.  */
  732. int
  733. recv(s,buf,len,flags)
  734. int s;        /* Socket index */
  735. char *buf;    /* User buffer */
  736. int len;    /* Max length to receive */
  737. int flags;    /* Unused; will eventually select oob data, etc */
  738. {
  739.     struct mbuf *bp;
  740.     int cnt;
  741.  
  742.     if(len == 0)
  743.         return 0;    /* Otherwise would be interp as "all" */
  744.  
  745.     cnt = recv_mbuf(s,&bp,len,flags,NULLCHAR,(int *)NULL);
  746.     if(cnt > 0){
  747.         cnt = min(cnt,len);
  748.         pullup(&bp,buf,cnt);
  749.         free_p(bp);
  750.     }
  751.     return cnt;
  752. }
  753. /* Higher level receive routine, intended for datagram sockets. Can also
  754.  * be used for connection-oriented sockets, although from and fromlen are
  755.  * ignored.
  756.  */
  757. int
  758. recvfrom(s,buf,len,flags,from,fromlen)
  759. int s;        /* Socket index */
  760. char *buf;    /* User buffer */
  761. int len;    /* Maximum length */
  762. int flags;    /* Unused; will eventually select oob data, etc */
  763. char *from;    /* Source address, only for datagrams */
  764. int *fromlen;    /* Length of source address */
  765. {
  766.     struct mbuf *bp;
  767.     register int cnt;
  768.  
  769.     cnt = recv_mbuf(s,&bp,len,flags,from,fromlen);
  770.     if(cnt > 0){
  771.         cnt = min(cnt,len);
  772.         pullup(&bp,buf,cnt);
  773.         free_p(bp);
  774.     }
  775.     return cnt;
  776. }
  777. /* High level send routine */
  778. int
  779. send(s,buf,len,flags)
  780. int s;        /* Socket index */
  781. char *buf;    /* User buffer */
  782. int len;    /* Length of buffer */
  783. int flags;    /* Unused; will eventually select oob data, etc */
  784. {
  785.     register struct mbuf *bp;
  786.     struct sockaddr sock;
  787.     int i = sizeof(sock);
  788.  
  789.     if(getpeername(s,(char *)&sock,&i) == -1)
  790.         return -1;
  791.     bp = qdata(buf,len);
  792.     return send_mbuf(s,bp,flags,(char *)&sock,i);
  793. }
  794. /* High level send routine, intended for datagram sockets. Can be used on
  795.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  796.  */
  797. int
  798. sendto(s,buf,len,flags,to,tolen)
  799. int s;        /* Socket index */
  800. char *buf;    /* User buffer */
  801. int len;    /* Length of buffer */
  802. int flags;    /* Unused; will eventually select oob data, etc */
  803. char *to;    /* Destination, only for datagrams */
  804. int tolen;    /* Length of destination */
  805. {
  806.     register struct mbuf *bp;
  807.  
  808.     bp = qdata(buf,len);
  809.     return send_mbuf(s,bp,flags,to,tolen);
  810. }
  811. /* Return local name passed in an earlier bind() call */
  812. int
  813. getsockname(s,name,namelen)
  814. int s;        /* Socket index */
  815. char *name;    /* Place to stash name */
  816. int *namelen;    /* Length of same */
  817. {
  818.     register struct usock *up;
  819.  
  820.     if((up = itop(s)) == NULLUSOCK){
  821.         errno = EBADF;
  822.         return -1;
  823.     }
  824.     if(name == NULLCHAR || namelen == (int *)NULL){
  825.         errno = EFAULT;
  826.         return -1;
  827.     }
  828.     if(up->name == NULLCHAR){
  829.         /* Not bound yet */
  830.         *namelen = 0;
  831.         return 0;
  832.     }
  833.     if(up->name != NULLCHAR){
  834.         *namelen = min(*namelen,up->namelen);
  835.         memcpy(name,up->name,*namelen);
  836.     }
  837.     return 0;
  838. }
  839. /* Get remote name, returning result of earlier connect() call. */
  840. int
  841. getpeername(s,peername,peernamelen)
  842. int s;            /* Socket index */
  843. char *peername;        /* Place to stash name */
  844. int *peernamelen;    /* Length of same */
  845. {
  846.     register struct usock *up;
  847.  
  848.     if((up = itop(s)) == NULLUSOCK){
  849.         errno = EBADF;
  850.         return -1;
  851.     }
  852.     if(up->peername == NULLCHAR){
  853.         errno = ENOTCONN;
  854.         return -1;
  855.     }
  856.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  857.         errno = EFAULT;
  858.         return -1;
  859.     }
  860.     *peernamelen = min(*peernamelen,up->peernamelen);
  861.     memcpy(peername,up->peername,*peernamelen);
  862.     return 0;
  863. }
  864. /* Return length of protocol queue, either send or receive. */
  865. int
  866. socklen(s,rtx)
  867. int s;        /* Socket index */
  868. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  869. {
  870.     register struct usock *up;
  871.  
  872.     if((up = itop(s)) == NULLUSOCK){
  873.         errno = EBADF;
  874.         return -1;
  875.     }
  876.     if(up->cb.p == NULLCHAR){
  877.         errno = ENOTCONN;
  878.         return -1;
  879.     }
  880.     if(rtx < 0 || rtx > 1){
  881.         errno = EINVAL;
  882.         return -1;
  883.     }
  884.     switch(up->type){
  885.     case TYPE_TCP:
  886.         switch(rtx){
  887.         case 0:
  888.             return up->cb.tcb->rcvcnt;
  889.         case 1:
  890.             return up->cb.tcb->sndcnt;
  891.         }
  892.     case TYPE_UDP:
  893.         switch(rtx){
  894.         case 0:
  895.             return up->cb.udp->rcvcnt;
  896.         case 1:
  897.             return 0;
  898.         }
  899. #ifdef    AX25
  900.     case TYPE_AX25I:
  901.         switch(rtx){
  902.         case 0:
  903.             return len_mbuf(up->cb.ax25->rxq);
  904.         case 1:    /* Number of packets, not bytes */
  905.             return len_q(up->cb.ax25->txq);
  906.         }
  907.     case TYPE_AX25UI:
  908.         /* TO BE IMPLEMENTED */
  909.         return 0;
  910. #endif
  911.     case TYPE_RAW:
  912.         return len_q(up->cb.rip->rcvq);
  913.     }
  914.     /*NOTREACHED*/
  915. }
  916. /* Force retransmission. Valid only for connection-oriented sockets. */
  917. int
  918. sockkick(s)
  919. int s;    /* Socket index */
  920. {
  921.     register struct usock *up;
  922.  
  923.     if((up = itop(s)) == NULLUSOCK){
  924.         errno = EBADF;
  925.         return -1;
  926.     }
  927.     if(up->cb.p == NULLCHAR){
  928.         errno = ENOTCONN;
  929.         return -1;
  930.     }
  931.     switch(up->type){
  932.     case TYPE_TCP:
  933.         kick_tcp(up->cb.tcb);
  934.         break;
  935. #ifdef    AX25
  936.     case TYPE_AX25I:
  937.         kick_ax25(up->cb.ax25);
  938.         break;
  939. #endif
  940.     default:
  941.         /* Datagram sockets can't be kicked */
  942.         errno = EOPNOTSUPP;
  943.         return -1;
  944.     }
  945.     return 0;
  946. }
  947.  
  948. /* Get state of protocol. Valid only for connection-oriented sockets. */
  949. char *
  950. sockstate(s)
  951. int s;        /* Socket index */
  952. {
  953.     register struct usock *up;
  954.  
  955.     if((up = itop(s)) == NULLUSOCK){
  956.         errno = EBADF;
  957.         return NULLCHAR;
  958.     }
  959.     if(up->cb.p == NULLCHAR){
  960.         errno = ENOTCONN;
  961.         return NULLCHAR;
  962.     }
  963.     switch(up->type){
  964.     case TYPE_TCP:
  965.         return Tcpstates[up->cb.tcb->state];
  966. #ifdef    AX25
  967.     case TYPE_AX25I:
  968.         return Ax25states[up->cb.ax25->state];
  969. #endif
  970.     default:
  971.         /* Datagram sockets don't have state */
  972.         errno = EOPNOTSUPP;
  973.         return NULLCHAR;
  974.     }
  975.     /*NOTREACHED*/
  976. }
  977. /* Change owner of socket, return previous owner */
  978. struct proc *
  979. sockowner(s,newowner)
  980. int s;            /* Socket index */
  981. struct proc *newowner;    /* Process table address of new owner */
  982. {
  983.     register struct usock *up;
  984.     struct proc *pp;
  985.  
  986.     if((up = itop(s)) == NULLUSOCK){
  987.         errno = EBADF;
  988.         return NULLPROC;
  989.     }
  990.     pp = up->owner;
  991.     if(newowner != NULLPROC)
  992.         up->owner = newowner;
  993.     return pp;
  994. }
  995. /* Close down a socket three ways. Type 0 means "no more receives"; this
  996.  * replaces the incoming data upcall with a routine that discards further
  997.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  998.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  999.  * as "abort the connection".
  1000.  */
  1001. int
  1002. shutdown(s,how)
  1003. int s;        /* Socket index */
  1004. int how;    /* (see above) */
  1005. {
  1006.     register struct usock *up;
  1007.  
  1008.     if((up = itop(s)) == NULLUSOCK){
  1009.         errno = EBADF;
  1010.         return -1;
  1011.     }
  1012.     if(up->cb.p == NULLCHAR){
  1013.         errno = ENOTCONN;
  1014.         return -1;
  1015.     }
  1016.     switch(up->type){
  1017.     case TYPE_TCP:
  1018.         switch(how){
  1019.         case 0:    /* No more receives -- replace upcall */
  1020.             up->cb.tcb->r_upcall = trdiscard;
  1021.             break;
  1022.         case 1:    /* Send EOF */
  1023.             close_tcp(up->cb.tcb);
  1024.             break;
  1025.         case 2:    /* Blow away TCB */
  1026.             reset_tcp(up->cb.tcb);
  1027.             up->cb.tcb = NULLTCB;
  1028.             break;
  1029.         }
  1030.         break;
  1031. #ifdef    AX25
  1032.     case TYPE_AX25I:
  1033.         switch(how){
  1034.         case 0:
  1035.         case 1:    /* Attempt regular disconnect */
  1036.             disc_ax25(up->cb.ax25);
  1037.             break;
  1038.         case 2: /* Blow it away */
  1039.             reset_ax25(up->cb.ax25);
  1040.             up->cb.ax25 = NULLAX25;
  1041.             break;
  1042.         }
  1043.         break;        
  1044. #endif
  1045.     case TYPE_RAW:
  1046.         close_s(s);
  1047.         break;
  1048.     default:
  1049.         errno = EOPNOTSUPP;
  1050.         return -1;
  1051.     }
  1052.     return 0;
  1053. }
  1054. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1055.  * TCP socket, if possible
  1056.  */
  1057. int
  1058. close_s(s)
  1059. int s;        /* Socket index */
  1060. {
  1061.     register struct usock *up;
  1062.  
  1063.     if((up = itop(s)) == NULLUSOCK){
  1064.         errno = EBADF;
  1065.         return -1;
  1066.     }
  1067.     switch(up->type){
  1068.     case TYPE_TCP:
  1069.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1070.             up->cb.tcb->r_upcall = trdiscard;
  1071.             /* Tell the CLOSED upcall there's no more socket */
  1072.             up->cb.tcb->user = -1;
  1073.             close_tcp(up->cb.tcb);
  1074.         }
  1075.         break;
  1076.     case TYPE_UDP:
  1077.         if(up->cb.udp != NULLUDP){
  1078.             psignal(&up->cb.udp->rcvq,0); /* Unblock any reads */
  1079.             del_udp(up->cb.udp);
  1080.         }
  1081.         break;
  1082. #ifdef    AX25
  1083.     case TYPE_AX25I:
  1084.         if(up->cb.ax25 != NULLAX25){
  1085.             psignal(&up->cb.ax25->rxq,0); /* Unblock any reads */
  1086.             /* Tell the CLOSED upcall there's no more socket */
  1087.             up->cb.ax25->user = -1;
  1088.             disc_ax25(up->cb.ax25);
  1089.         }
  1090.         break;
  1091.     case TYPE_AX25UI:
  1092.         axui_sock = -1;
  1093.         free_q(&bcq);
  1094.         psignal(&bcq,0);    /* Unblock any reads */
  1095.         break;
  1096. #endif
  1097.     case TYPE_RAW:
  1098.         psignal(&up->cb.rip->rcvq,0);     /* Unblock any reads */
  1099.         del_ip(up->cb.rip);
  1100.         break;
  1101.     default:
  1102.         errno = EOPNOTSUPP;
  1103.         return -1;
  1104.     }
  1105.     if(up->name != NULLCHAR)
  1106.         free(up->name);
  1107.     if(up->peername != NULLCHAR)
  1108.         free(up->peername);
  1109.  
  1110.     up->cb.p = NULLCHAR;
  1111.     up->name = up->peername = NULLCHAR;
  1112.     up->type = NOTUSED;
  1113.     psignal(up,0);    /* Wake up anybody doing an accept() */
  1114.     return 0;
  1115. }
  1116. /* Return ASCII string giving reason for connection closing */
  1117. char *
  1118. sockerr(s)
  1119. int s;    /* Socket index */
  1120. {
  1121.     register struct usock *up;
  1122.  
  1123.     if((up = itop(s)) == NULLUSOCK){
  1124.         errno = EBADF;
  1125.         return NULLCHAR;
  1126.     }
  1127.     switch(up->type){
  1128. #ifdef    AX25
  1129.     case TYPE_AX25I:
  1130.         if(up->cb.ax25 != NULLAX25)
  1131.             return NULLCHAR;    /* nothing wrong */
  1132.         return Axreasons[up->errcodes[0]];
  1133. #endif
  1134.     case TYPE_TCP:
  1135.         if(up->cb.tcb != NULLTCB)
  1136.             return NULLCHAR;    /* nothing wrong */        
  1137.         return Tcpreasons[up->errcodes[0]];
  1138.     default:
  1139.         errno = EOPNOTSUPP;    /* not yet, anyway */
  1140.         return NULLCHAR;
  1141.     }
  1142. }
  1143. /* End of user socket primitives, begin user utility subroutines */
  1144.  
  1145. /* Receive a newline-terminated line from a socket, returning # chars read */
  1146. int
  1147. recvline(s,buf,len)
  1148. int s;        /* Socket index */
  1149. char *buf;    /* User buffer */
  1150. unsigned len;    /* Length of buffer */
  1151. {
  1152.     char c;
  1153.     int cnt = 0;
  1154.  
  1155.     while(len-- != 0){
  1156.         if(recv(s,&c,1,0) != 1)
  1157.             return -1;
  1158.         *buf++ = c;
  1159.         cnt++;
  1160.         if(uchar(c) == '\n')
  1161.             break;
  1162.     }
  1163.     return cnt;
  1164. }
  1165. /* Do printf on a user socket */
  1166. #if    defined(__STDC__) || defined(__TURBOC__)
  1167. int
  1168. usprintf(int s,char *fmt,...)
  1169. {
  1170.     register struct mbuf *bp;
  1171.     int len;
  1172.     va_list args;
  1173.  
  1174.     va_start(args,fmt);
  1175.     bp = alloc_mbuf(200);
  1176.     len = vsprintf(bp->data,fmt,args);
  1177.     bp->cnt = strlen(bp->data);
  1178.     send_mbuf(s,bp,0,NULLCHAR,0);
  1179.     va_end(args);
  1180.     return len;
  1181. }
  1182. #else
  1183. /*VARARGS*/
  1184. int
  1185. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6)
  1186. int s;            /* Socket index */
  1187. char *fmt;        /* Message format */
  1188. int arg1,arg2,arg3;    /* Arguments */
  1189. int arg4,arg5,arg6;
  1190. {
  1191.     register struct mbuf *bp;
  1192.     int len;
  1193.  
  1194.     bp = alloc_mbuf(200);
  1195.     len = sprintf(bp->data,fmt,arg1,arg2,arg3,arg4,arg5,arg6);
  1196.     bp->cnt = strlen(bp->data);
  1197.     send_mbuf(s,bp,0,NULLCHAR,0);
  1198.     return len;
  1199. }
  1200. #endif
  1201. /* Convert a socket (address + port) to an ascii string of the form
  1202.  * aaa.aaa.aaa.aaa:ppppp
  1203.  */
  1204. char *
  1205. psocket(s)
  1206. struct sockaddr *s;    /* Pointer to structure to decode */
  1207. {
  1208.     char tmp[11];
  1209.     static char buf[30];
  1210.     union sp sp;
  1211.     struct socket socket;
  1212.  
  1213.     switch(s->sa_family){
  1214.     case AF_INET:
  1215.         sp.in = (struct sockaddr_in *)s;
  1216.         socket.address = sp.in->sin_addr.s_addr;
  1217.         socket.port = sp.in->sin_port;
  1218.         strcpy(buf,pinet(&socket));
  1219.         break;
  1220. #ifdef    AX25
  1221.     case AF_AX25:
  1222.         sp.ax = (struct sockaddr_ax *)s;
  1223.         pax25(tmp,&sp.ax->ax25_addr);
  1224.         sprintf(buf,"%s on %s",tmp,sp.ax->iface);
  1225.         break;
  1226. #endif
  1227.     }
  1228.     return buf;
  1229. }
  1230. /* Read a character from a socket with stream buffering */
  1231. int
  1232. recvchar(s,bpp)
  1233. int s;            /* Socket index */
  1234. struct mbuf **bpp;    /* User-supplied buffer pointer */
  1235. {
  1236.     char c;
  1237.  
  1238.     if(*bpp == NULLBUF)
  1239.         recv_mbuf(s,bpp,0,0,NULLCHAR,0);    /* Replenish */
  1240.  
  1241.     if(pullup(bpp,&c,1) != 1)
  1242.         return -1;
  1243.     return uchar(c);
  1244. }
  1245. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1246. void
  1247. freesock(pp)
  1248. struct proc *pp;
  1249. {
  1250.     register struct usock *up;
  1251.     register int i;
  1252.  
  1253.     for(i=0;i < Nusock;i++){
  1254.         up = &Usock[i];
  1255.         if(up->type != NOTUSED && up->owner == pp)
  1256.             shutdown(i,2);
  1257.     }
  1258. }
  1259.  
  1260. /* End of user utility subroutines, start internal subroutines */
  1261.  
  1262. /* UDP receive upcall routine */
  1263. static void
  1264. s_urcall(udp,cnt)
  1265. struct udp_cb *udp;
  1266. int cnt;
  1267. {
  1268.     psignal(&udp->rcvq,1);
  1269. }
  1270. /* TCP receive upcall routine */
  1271. static void
  1272. s_trcall(tcb,cnt)
  1273. struct tcb *tcb;
  1274. int cnt;
  1275. {
  1276.     /* Wake up anybody waiting for data, and let them run */
  1277.     psignal(&tcb->rcvq,1);
  1278.     pwait(NULL);
  1279. }
  1280. /* TCP transmit upcall routine */
  1281. static void
  1282. s_ttcall(tcb,cnt)
  1283. struct tcb *tcb;
  1284. int cnt;
  1285. {
  1286.     /* Wake up anybody waiting to send data, and let them run */
  1287.     psignal(&tcb->sndq,1);
  1288.     pwait(NULL);
  1289. }
  1290. /* TCP state change upcall routine */
  1291. static void
  1292. s_tscall(tcb,old,new)
  1293. struct tcb *tcb;
  1294. int old,new;
  1295. {
  1296.     int s,ns;
  1297.     struct usock *up,*nup,*oup;
  1298.     union sp sp;
  1299.  
  1300.     s = tcb->user;
  1301.     oup = up = itop(s);
  1302.  
  1303.     switch(new){
  1304.     case CLOSED:
  1305.         /* Clean up. If the user has already closed the socket,
  1306.          * then up will be null (s was set to -1 by the close routine).
  1307.          * If not, then this is an abnormal close (e.g., a reset)
  1308.          * and clearing out the pointer in the socket structure will
  1309.          * prevent any further operations on what will be a freed
  1310.          * control block. Also wake up anybody waiting on events
  1311.          * related to this tcb so they will notice it disappearing.
  1312.          */
  1313.         psignal(&tcb->rcvq,0);
  1314.         psignal(&tcb->sndq,0);
  1315.         if(up != NULLUSOCK){
  1316.             up->cb.tcb = NULLTCB;
  1317.             up->errcodes[0] = tcb->reason;
  1318.             up->errcodes[1] = tcb->type;
  1319.             up->errcodes[2] = tcb->code;
  1320.         }
  1321.         del_tcp(tcb);
  1322.         break;
  1323.     case SYN_RECEIVED:
  1324.         /* Handle an incoming connection. If this is a server TCB,
  1325.          * then we're being handed a "clone" TCB and we need to
  1326.          * create a new socket structure for it. In either case,
  1327.          * find out who we're talking to and wake up the guy waiting
  1328.          * for the connection.
  1329.          */
  1330.         if(tcb->flags.clone){
  1331.             /* Clone the socket */
  1332.             ns = socket(AF_INET,SOCK_STREAM,0);
  1333.             nup = &Usock[ns];
  1334.             memcpy((char *)nup,(char *)up,sizeof(struct usock));
  1335.             tcb->user = ns;
  1336.             nup->cb.tcb = tcb;
  1337.             /* Allocate new memory for the name areas */
  1338.             nup->name = malloc(SOCKSIZE);
  1339.             nup->peername = malloc(SOCKSIZE);
  1340.             /* Store the new socket # in the old one */
  1341.             up->rdysock = ns;
  1342.             up = nup;
  1343.             s = ns;
  1344.         } else {
  1345.             /* Allocate space for the peer's name */
  1346.             up->peername = malloc(SOCKSIZE);
  1347.             /* Store the old socket # in the old socket */
  1348.             up->rdysock = s;
  1349.         }
  1350.         /* Load the addresses. Memory for the name has already
  1351.          * been allocated, either above or in the original bind.
  1352.          */
  1353.         sp.p = up->name;
  1354.         sp.in->sin_family = AF_INET;
  1355.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1356.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1357.         up->namelen = SOCKSIZE;
  1358.  
  1359.         sp.p = up->peername;
  1360.         sp.in->sin_family = AF_INET;
  1361.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1362.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1363.         up->peernamelen = SOCKSIZE;
  1364.  
  1365.         /* Wake up the guy accepting it, and let him run */
  1366.         psignal(oup,1);
  1367.         pwait(NULL);
  1368.         break;
  1369.     default:    /* Ignore all other state transitions */
  1370.         break;
  1371.     }
  1372.     psignal(&tcb->state,0);    /* In case anybody's waiting */
  1373. }
  1374. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1375.  * close_s until the TCB disappears.
  1376.  */
  1377. static void
  1378. trdiscard(tcb,cnt)
  1379. struct tcb *tcb;
  1380. int cnt;
  1381. {
  1382.     struct mbuf *bp;
  1383.  
  1384.     recv_tcp(tcb,&bp,cnt);
  1385.     free_p(bp);
  1386. }
  1387. #ifdef    AX25
  1388. /* AX.25 receive upcall */
  1389. void
  1390. s_arcall(axp,cnt)
  1391. struct ax25_cb *axp;
  1392. int cnt;
  1393. {
  1394.     /* Wake up anyone waiting, and let them run */
  1395.     psignal(&axp->rxq,1);
  1396.     pwait(NULL);
  1397. }
  1398. /* AX.25 transmit upcall */
  1399. void
  1400. s_atcall(axp,cnt)
  1401. struct ax25_cb *axp;
  1402. int cnt;
  1403. {
  1404.     /* Wake up anyone waiting, and let them run */
  1405.     psignal(&axp->txq,1);
  1406.     pwait(NULL);
  1407. }
  1408. /* AX25 state change upcall routine */
  1409. void
  1410. s_ascall(axp,old,new)
  1411. register struct ax25_cb *axp;
  1412. int old,new;
  1413. {
  1414.     int s;
  1415.     struct usock *up;
  1416.  
  1417.     s = axp->user;
  1418.     up = itop(s);
  1419.  
  1420.     switch(new){
  1421.     case DISCONNECTED:
  1422.         /* Clean up. If the user has already closed the socket,
  1423.          * then up will be null (s was set to -1 by the close routine).
  1424.          * If not, then this is an abnormal close (e.g., a reset)
  1425.          * and clearing out the pointer in the socket structure will
  1426.          * prevent any further operations on what will be a freed
  1427.          * control block. Also wake up anybody waiting on events
  1428.          * related to this block so they will notice it disappearing.
  1429.          */
  1430.         psignal(&axp->rxq,0);
  1431.         psignal(&axp->txq,0);
  1432.         if(up != NULLUSOCK){
  1433.             up->errcodes[0] = axp->reason;
  1434.             up->cb.ax25 = NULLAX25;
  1435.         }
  1436.         del_ax25(axp);
  1437.         break;
  1438.     default:    /* Other transitions are ignored */
  1439.         break;
  1440.     }
  1441.     psignal(&axp->state,0);    /* In case anybody's waiting */
  1442. }
  1443. #endif
  1444.  
  1445. /* Socket status display command */
  1446. int
  1447. dosock(argc,argv)
  1448. int argc;
  1449. char *argv[];
  1450. {
  1451.     register struct usock *up;
  1452.     int s;
  1453.  
  1454.     if(argc < 2){
  1455.         printf("S# Type    PCB      Owner\n");
  1456.         for(s=0;s<Nusock;s++){
  1457.             up = &Usock[s];
  1458.             if(up->type == NOTUSED)
  1459.                 continue;
  1460.             printf("%2d %-8s%-8lx %lx (%s)\n",
  1461.              s,Socktypes[up->type],ptol(up->cb.p),
  1462.              ptol(up->owner),up->owner->name);
  1463.         }
  1464.         return 0;
  1465.     }
  1466.     s = atoi(argv[1]);
  1467.     if(s < 0 || s >= Nusock){
  1468.         printf("Number out of range\n");
  1469.         return 1;
  1470.     }
  1471.     up = &Usock[s];
  1472.     switch(up->type){
  1473.     case NOTUSED:
  1474.         printf("Not in use\n");
  1475.         break;
  1476.     case TYPE_TCP:
  1477.         printf("TCP %lx\n",ptol(up->cb.tcb));
  1478.         if(up->cb.tcb != NULLTCB)
  1479.             st_tcp(up->cb.tcb);
  1480.         break;
  1481.     case TYPE_UDP:
  1482.         printf("UDP %lx\n",ptol(up->cb.udp));
  1483.         if(up->cb.udp != NULLUDP)
  1484.             st_udp(up->cb.udp,0);
  1485.         break;
  1486. #ifdef    AX25
  1487.     case TYPE_AX25I:
  1488.         printf("AX25I %lx\n",ptol(up->cb.ax25));
  1489.         if(up->cb.ax25 != NULLAX25)
  1490.             st_ax25(up->cb.ax25);
  1491.         break;
  1492.     case TYPE_AX25UI:
  1493.         printf("AX25 UI\n");
  1494.         break;
  1495. #endif
  1496.     }
  1497.     return 0;    
  1498. }
  1499. /* Verify address family and length according to the socket type */
  1500. static int
  1501. checkaddr(type,name,namelen)
  1502. char *name;
  1503. int type;
  1504. int namelen;
  1505. {
  1506.     register struct sockaddr *sp;
  1507.  
  1508.     sp = (struct sockaddr *)name;
  1509.     /* Verify length and address family according to protocol */
  1510.     switch(type){
  1511.     case TYPE_TCP:
  1512.     case TYPE_UDP:
  1513.         if(sp->sa_family != AF_INET
  1514.          || namelen != sizeof(struct sockaddr_in))
  1515.             return -1;
  1516.         break;
  1517.     case TYPE_AX25I:
  1518.     case TYPE_AX25UI:
  1519.         if(sp->sa_family != AF_AX25
  1520.          || namelen != sizeof(struct sockaddr_ax))
  1521.             return -1;
  1522.         break;
  1523.     }
  1524.     return 0;
  1525. }
  1526. /* Convert a socket index to an internal user socket structure pointer */
  1527. static struct usock *
  1528. itop(s)
  1529. register int s;    /* Socket index */
  1530. {
  1531.     register struct usock *up;
  1532.  
  1533.     if(s < 0 || s >= Nusock)
  1534.         return NULLUSOCK;
  1535.  
  1536.     up = &Usock[s];
  1537.  
  1538.     if(up->type == NOTUSED)
  1539.         return NULLUSOCK;
  1540.     return up;
  1541. }
  1542. /* Issue an automatic bind of a local address */
  1543. static void
  1544. autobind(s,af)
  1545. int s,af;
  1546. {
  1547.     struct sockaddr sockaddr;
  1548.     union sp sp;
  1549.  
  1550.     sp.p = (char *)&sockaddr;
  1551.     switch(af){
  1552.     case AF_INET:
  1553.         sp.in->sin_family = AF_INET;
  1554.         sp.in->sin_addr.s_addr = Ip_addr;
  1555.         sp.in->sin_port = Lport++;
  1556.         bind(s,sp.p,SOCKSIZE);
  1557.         break;
  1558. #ifdef    AX25
  1559.     case AF_AX25:
  1560.         sp.ax->sax_family = AF_AX25;
  1561.         memcpy(sp.ax->ax25_addr.call,Mycall.call,ALEN);
  1562.         sp.ax->ax25_addr.ssid = Mycall.ssid;
  1563.         bind(s,sp.p,SOCKSIZE);
  1564.         break;
  1565. #endif
  1566.     }
  1567. }
  1568.  
  1569.  
  1570.